3.4 Button system

All classes derived from the tabstop base class link together in order of declaration and the whole construction we call the button system. The button system may be considered as a ring of button groups and tabstop Objects. Button groups are itself the rings of buttons. The tabstop Objects start linking to each other as the butsystem class is declared.

** Button groups must be declared after the declaration of the button system. The good style of programming is to declare the button system first in the procedure.

Constructor:

butsystem(int master = 0); // Is not master by default

The button system has access to the Stack of the Objects (sect.4) only if master=MASTER, i.e. non-zero. Otherwise the button system will only control tabstop Objects and button groups. Usually only the button system in the main() is declared as MASTER.

Data members:

unsigned int ConStatus;// status of kbd and mouse
unsigned char key0; // ascii codes of last keystroke
unsigned char key1;

These data members can be used by the Background procedure. The Loop method sets them when actions occurred on the console. The key0 keeps ASCII code of the key stricken last. If it is zero then the key1 keeps extended ASCII code. Using ConStatus you can determine if the key was hit just now. This flag is cleared during the next polling of console. If (bsMain.ConStatus & KBD_HIT) == 1 the key was hit.

Methods:

int RegisterMenu(int (far *MenuSysFunc)(void));

Registers the menu system function with the button system. Returns TRUE if registration succeeded or FALSE if failed.

void NextTabStop(void);
void PrevTabStop(void);

To make the next or the previous tabstop object active. Usually this can be done from console striking Tab or Shift-Tab keys. These methods allow you to do this from the program. There may be problems using this functions when there are tabstop Object which are waiting input from the keyboard when activated (for example the TSInbox Object). To skip such Object you have to provide the input for this Object. For example if the next Object is the TSInbox Object you can write the following code:

ungetch(13);            // provide CR for the TSInbox Object
bsMain.NextTabStop();  // now the TSInbox Object get CR and
                  // program returns from the Activate method

void NextButton(void);
void PrevButton(void);

To make the next or the previous button in active group active. Usually this can be done from console by arrow keys. These methods allow you to do this from the program.

void Loop(void (far *BkgrndProc)(void));

Puts button system into effect. Before calling this function you should be certain that you have declared all the objects. This method organizes what we call Virtual Panels Loop, which polls the console and, when the key is pushed or mouse is clicked, takes the necessary actions. Those include dragging the object on the screen, pushing the button and calling the button procedure, activation of the menu system and so on. After each polling Loop calls the user supplied background function void far BkgrndProc(). This function takes the control on the program and the polling resumes when the program returns from BkgrndProc(). In section 5 we offer the style of writing BkgrndProc(). Of course you can regard BkgrndProc() as a foreground routine and the Loop as a background routine, which takes control under your permission. This allows you to perform the data processing and presentation, while controlling the flow of program from console. Of course BkgrndProc() hardly can be used for the real time data acquisition. The use of the interrupt handlers and the mail boxes is the best way to do this.

void SendMessage(int messg);

Sends the message messg to the Virtual Panels Loop. In this version Loop method responds only to messages:

MSG_EXIT
has the same effect as striking ESC on the keyboard. Loop breaks and the next statement after the Loop in the program is executed.

MSG_NEXTTABSTOP, MSG_PREVTABSTOP
have the same effect as striking TAB or Shift-TAB on the keyboard.

Example 3.1.2. :

//------------------  CONFIRM ----------------------
//----- returns FALSE if 'No' button was pressed,
//-----         TRUE     'Yes'
int resp=0;     // Status register 1- Yes,  0 - No. Default is No
butsystem *pbsYN;

void far bpYes(void)
        { resp=1; pbsYN->SendMessage(MSG_EXIT);} // exit Loop
void far bpNo(void)
        { resp=0; pbsYN->SendMessage(MSG_EXIT);} // exit Loop

int _Cdecl Confirm(char *mess)
{
pbsYN = new butsystem;
Outbox Ask( maxx>>2, maxy>>2,   // coord. of LEFT-TOP corner
            POPUP, "Confirm",   // title of box
            strlen(mess)+2, 5,  // size of box
            FRAMED, procNULL,  // no paint procedure is defined
            0,1, 0,1); // title and text use raster fonts
butgrp YesNo( (Ask.xmax+Ask.x0-110)>>1, Ask.ymax-40, 50, 21, HORIZ, 10);
 button Yes("Yes",'y','Y',bpYes);
 button No("No",'n','N',bpNo);

 Ask.Paint();
 Ask.SetTextJustify( CENTER_TEXT );
 Ask.Putn("");       // skip one line
 Ask.Put( mess,1);   // and print your suggestion
 YesNo.Paint();

 pbsYN->NextButton();
 pbsYN->Loop(procDummy);        // Now wait responce
 delete pbsYN;

 Ask.Remove();  // remove box from the screen
 return resp;   // return TRUE if Yes, FALSE if No
}

This is an example how to organize confirmation box. When you call in your program e.g.

 Confirm("Save the data ?");
on the screen appears the box with text "Save the data ?" and two buttons beneath: "Yes" and "No". That is the new button system which consists of the one button group with two buttons. When you choose one of the buttons, the new button system quits, the preceding one restores and the box disappears. You can also strike ESC key to quit the new button system, but in this case the default value of resp will be returned.